home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-20
/
rs0422.zip
/
LEVEL1
/
RTIMER.AS
< prev
next >
Wrap
Text File
|
1989-11-14
|
4KB
|
166 lines
*TITLE RTIMER - 'Timer Subroutines for MULRPT'
GLOBAL SETTMR,TICK
GLOBAL _COLD
; Routines use a single CTC channel to implement a multi-
; channel timer capability. The SETTMR subroutine is called
; to set a timer. Each "tick" of the CTC interrupt calls
; the TICK subroutine, which counts down the timers. When
; a timer expires its associated subroutine is called.
; If running on a TNC 2 there is no CTC and the SYNC line
; from the console is used, and we are called from I_EXT
*INCLUDE RCONFIG.LIB
; Timer data structure definition
CNT EQU 0 ;Timer count, 2 bytes
ARG EQU 2 ;Service sub. calling arg, 2 bytes
SVC EQU 4 ;Address of service subroutine
TDSLEN EQU 6 ;Size of data structure
*Heading 'SETTMR - Timer Initialization Subroutine'
; SETTMR - Set a timer channel.
;
; *** WARNING: Enter with interrupts disabled -- or else!
;
; Entry parameters:
; A = Channel number.
; BC = Timer value in ticks.
; DE = Argument to be passed to the service
; subroutine in DE when called.
; HL = Address of service subroutine.
; Return parameters:
; Registers AF, BC, DE, HL trashed.
PSECT text
SETTMR:
PUSH HL ;Save during calculations
PUSH BC
LD L,A ;Make 16 bit channel number
ld a,h
or a ;is address of routine >8000h?
jp p,1f ;nope --> all ok
LD A,80h
LD (_COLD),A
JP 0
; Calculate data structure address for this channel
; LD L,A ;Make 16 bit channel number
1: LD H,0
ADD HL,HL ;Channel * 2
LD C,L ;Copy to BC
LD B,H
ADD HL,HL ;Channel * 4
ADD HL,BC ;Channel * 6 (offset)
LD BC,TIMDS ;Get data structure base
ADD HL,BC ;Point to data structure
; Fill data structure.
POP BC ;Get time count
LD (HL),C ;Store it
INC HL
LD (HL),B
INC HL
LD (HL),E ;Store calling arg
INC HL
LD (HL),D
INC HL
POP DE ;Get service address
LD (HL),E ;Store it
INC HL
LD (HL),D
RET
*HEADING 'TICK - CTC Interrupt Handler'
; TICK - CTC interrupt service. Counts down each timer
; channel if active (i.e. count is non-zero). When count
; reaches zero, calls service subroutine.
TICK:
PUSH AF ;Save interrupted context
PUSH BC
PUSH DE
PUSH HL
PUSH IX
PUSH IY
; Loop executes once for each timer channel. (one extra for L2/L3 100ms tick)
LD A,NUMCH+1 ;Number of timers (and channels)
LD HL,TIMDS ;Base of data structures
TLOOP: LD (COUNT),A ;Set loop count
LD C,L ;Copy data structure pointer...
LD B,H ;...to BC for safekeeping
LD E,(HL) ;Get time count
INC HL
LD D,(HL)
LD A,D ;Test for zero count (inactive)
OR E
JR Z,NXTTMR ;Inactive, skip to next channel
DEC DE ;Count down one
LD (HL),D ;Update time count
DEC HL
LD (HL),E
LD A,D ;Is it zero now?
OR E
JR NZ,NXTTMR ;No, don't service it
INC HL ;Point to calling arg
INC HL
LD E,(HL) ;Get calling arg
INC HL
LD D,(HL)
INC HL
LD A,(HL) ;Get service address
INC HL
LD H,(HL)
LD L,A
PUSH BC ;Save data pointer
CALL VECTOR ;Call the service sub.
POP BC ;Restore data pointer
NXTTMR: LD HL,TDSLEN ;Offset to next data
ADD HL,BC
LD A,(COUNT) ;Get loop count
DEC A
JR NZ,TLOOP ;Continue
TMRXIT: POP IY ;Restore interrupted context
POP IX
POP HL
POP DE
POP BC
POP AF
COND CTC .eq. FALSE
RET ;Back to I_EXT (intr svc)
ENDC
COND CTC .eq. TRUE
EI
RETI ;Back to mainline
ENDC
VECTOR: ld a,h ;insure we are jumping to ROM
or a ;set flags
jp p,1f ;nope --> all ok
LD A,80h
LD (_COLD),A
JP 0 ;death - trash the switch
1: JP (HL) ;Vector to subroutine
PSECT bss
CNTR: DEFS 1 ;Counter to adjust H/W intr to a 10 ms tick
COUNT: DEFS 1 ;Loop counter
TIMDS: DEFS TDSLEN*(NUMCH+1) ;Note: this area is zeroed by
;the main program at reset
*HEADING 'Symbol Table'
END